/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2025-03-27 14:57:46
 * @LastEditTime : 2025-08-21 15:46:21
 * @FilePath     : \hal_driver\ll_gpio.c
 * @Description  : gpio低层驱动
 * @Version      : V1.0
 * @History      :
 * @Note         :
 */
/***************************************Includes***********************************/
#include "ll_gpio.h"

/************************************Private Macros********************************/
// #define


/**********************************Private Statement*******************************/


/***********************************Public Variables*******************************/



/**********************************Private Variables*******************************/



/**********************************Public Functions********************************/

/**
 * @brief gpio初始化
 * @param  gpio
 * @param  port             端口
 * @param  pinnum           管脚
 * @param  mode             输入输出模式
 * @param  pull             上下拉
 * @param  speed            速度
 * @param  af_num           复用号 仅复用模式可用
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_init(
    gpio_ll_t *gpio,
    uint32_t port,
    uint32_t pinnum,
    gpio_ll_mode_t mode,
    gpio_ll_outtype_t otype,
    gpio_ll_pull_t pull,
    gpio_ll_speed_t speed,
    uint32_t af_num) {
    gpio->af_num = af_num;
#if defined(GD32F407) || defined(GD32F10X_HD)
    gpio->port = port;
    gpio->pin = pinnum;
    // clang-format off
    switch(port) {
        case GPIOA: rcu_periph_clock_enable(RCU_GPIOA); break;
        case GPIOB: rcu_periph_clock_enable(RCU_GPIOB); break;
        case GPIOC: rcu_periph_clock_enable(RCU_GPIOC); break;
        case GPIOD: rcu_periph_clock_enable(RCU_GPIOD); break;
        case GPIOE: rcu_periph_clock_enable(RCU_GPIOE); break;
        case GPIOF: rcu_periph_clock_enable(RCU_GPIOF); break;
        case GPIOG: rcu_periph_clock_enable(RCU_GPIOG); break;
    #if defined(GD32F407)
        case GPIOH: rcu_periph_clock_enable(RCU_GPIOH); break;
        case GPIOI: rcu_periph_clock_enable(RCU_GPIOI); break;
    #endif
        default: return -1;
    }
    #if defined(GD32F407)
    switch (mode) {
        case GPIO_LL_MODE_INPUT: gpio->mode = GPIO_MODE_INPUT; break;
        case GPIO_LL_MODE_OUTPUT: gpio->mode = GPIO_MODE_OUTPUT; break;
        case GPIO_LL_MODE_ANALOG: gpio->mode = GPIO_MODE_ANALOG; break;
        case GPIO_LL_MODE_AF: gpio->mode = GPIO_MODE_AF; break;
        default: gpio->mode = GPIO_MODE_INPUT; break;
    }
    switch (otype) {
        case GPIO_LL_OTYPE_PP: gpio->otype = GPIO_OTYPE_PP; break;
        case GPIO_LL_OTYPE_OD: gpio->otype = GPIO_OTYPE_OD; break;
        default: gpio->otype = GPIO_OTYPE_PP; break;
    }
    switch (pull) {
        case GPIO_LL_PULL_NO: gpio->pull = GPIO_PUPD_NONE; break;
        case GPIO_LL_PULL_UP: gpio->pull = GPIO_PUPD_PULLUP; break;
        case GPIO_LL_PULL_DOWN: gpio->pull = GPIO_PUPD_PULLDOWN; break;
        default: gpio->pull = GPIO_PUPD_NONE; break;
    }
    #endif
    switch (speed) {
    #if defined(GD32F407)
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_OSPEED_2MHZ; break;
        case GPIO_LL_SPEED_VERY_HIGH: gpio->speed = GPIO_OSPEED_MAX; break;
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_OSPEED_50MHZ; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_OSPEED_25MHZ; break;
    #elif defined(GD32F10X_HD)
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_OSPEED_2MHZ; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_OSPEED_10MHZ; break;
        case GPIO_LL_SPEED_VERY_HIGH:
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_OSPEED_50MHZ;  break;
    #endif
        default: gpio->speed = GPIO_OSPEED_2MHZ; break;
    }
    
    #if defined(GD32F407)
    gpio_mode_set(gpio->port, gpio->mode, gpio->pull, gpio->pin);
    gpio_output_options_set(gpio->port, gpio->otype, gpio->speed, gpio->pin);
    if (mode == GPIO_LL_MODE_AF) {
        gpio_af_set(gpio->port, af_num, gpio->pin);
    }
    #elif defined(GD32F10X_HD)
    gpio->mode = mode;
    gpio->otype = otype;
    gpio->pull = pull;
    gpio->speed = speed;
    if (mode == GPIO_LL_MODE_INPUT) {
        switch (pull) {
            case GPIO_LL_PULL_NO: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_UP: gpio_init(gpio->port, GPIO_MODE_IPU, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_DOWN: gpio_init(gpio->port, GPIO_MODE_IPD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
        }
    } else if (mode == GPIO_LL_MODE_OUTPUT){
        switch (otype) {
            case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_OUT_PP, gpio->speed, gpio->pin); break;
            case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
        }
    } else if (mode == GPIO_LL_MODE_ANALOG) {
        gpio_init(gpio->port, GPIO_MODE_AIN, gpio->speed, gpio->pin);
    } else if (mode == GPIO_LL_MODE_AF) {
        rcu_periph_clock_enable(RCU_AF);
        switch (otype) {
        case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_AF_OD, gpio->speed, gpio->pin); break;
        case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_AF_PP, gpio->speed, gpio->pin); break;
        default: return -1;
        }
    }
    #endif
    // clang-format on
    return 0;
#elif defined(STM32F40_41xxx) || defined(STM32F10X_HD)
    // clang-format off
    gpio->port = port;
    gpio->pin = pinnum;
    uint32_t af_source;
    #if defined(STM32F40_41xxx)
    switch(port) {
        case (uint32_t)GPIOA: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); break;
        case (uint32_t)GPIOB: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); break;
        case (uint32_t)GPIOC: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); break;
        case (uint32_t)GPIOD: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); break;
        case (uint32_t)GPIOE: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); break;
        case (uint32_t)GPIOF: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); break;
        case (uint32_t)GPIOG: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); break;
        case (uint32_t)GPIOH: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE); break;
        case (uint32_t)GPIOI: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI, ENABLE); break;
        case (uint32_t)GPIOJ: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOJ, ENABLE); break;
        case (uint32_t)GPIOK: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOK, ENABLE); break;
        default: return -1;
    }
    
    if (mode == GPIO_LL_MODE_AF) {
        switch (gpio->pin) {
            case GPIO_Pin_0: af_source = GPIO_PinSource0; break;
            case GPIO_Pin_1: af_source = GPIO_PinSource1; break;
            case GPIO_Pin_2: af_source = GPIO_PinSource2; break;
            case GPIO_Pin_3: af_source = GPIO_PinSource3; break;
            case GPIO_Pin_4: af_source = GPIO_PinSource4; break;
            case GPIO_Pin_5: af_source = GPIO_PinSource5; break;
            case GPIO_Pin_6: af_source = GPIO_PinSource6; break;
            case GPIO_Pin_7: af_source = GPIO_PinSource7; break;
            case GPIO_Pin_8: af_source = GPIO_PinSource8; break;
            case GPIO_Pin_9: af_source = GPIO_PinSource9; break;
            case GPIO_Pin_10: af_source = GPIO_PinSource10; break;
            case GPIO_Pin_11: af_source = GPIO_PinSource11; break;
            case GPIO_Pin_12: af_source = GPIO_PinSource12; break;
            case GPIO_Pin_13: af_source = GPIO_PinSource13; break;
            case GPIO_Pin_14: af_source = GPIO_PinSource14; break;
            case GPIO_Pin_15: af_source = GPIO_PinSource15; break;
            default: return -1; break;
        }
        GPIO_PinAFConfig((void *)gpio->port, af_source, af_num);
    }
    switch (mode) {
        case GPIO_LL_MODE_INPUT: gpio->mode = GPIO_Mode_IN; break;
        case GPIO_LL_MODE_OUTPUT: gpio->mode = GPIO_Mode_OUT; break;
        case GPIO_LL_MODE_AF: gpio->mode = GPIO_Mode_AF; break;
        case GPIO_LL_MODE_ANALOG: gpio->mode = GPIO_Mode_AN; break;
        default: gpio->mode = GPIO_Mode_IN; break;
    }
    switch (otype) {
        case GPIO_LL_OTYPE_PP: gpio->otype = GPIO_OType_PP; break;
        case GPIO_LL_OTYPE_OD: gpio->otype = GPIO_OType_OD; break;
        default: gpio->otype = GPIO_OType_PP; break;
    }
    switch (pull) {
        case GPIO_LL_PULL_NO: gpio->pull = GPIO_PuPd_NOPULL; break;
        case GPIO_LL_PULL_UP: gpio->pull = GPIO_PuPd_UP; break;
        case GPIO_LL_PULL_DOWN: gpio->pull = GPIO_PuPd_DOWN; break;
        default: gpio->pull = GPIO_PuPd_NOPULL; break;
    }
    switch (speed) {
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_Speed_2MHz; break;
        case GPIO_LL_SPEED_VERY_HIGH: gpio->speed = GPIO_Speed_100MHz; break;
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_Speed_50MHz; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_Speed_25MHz; break;
        default: gpio->speed = GPIO_Speed_2MHz; break;
    }
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio_cfg.GPIO_Mode = gpio->mode;
    gpio_cfg.GPIO_OType = gpio->otype;
    gpio_cfg.GPIO_PuPd = gpio->pull;
    gpio_cfg.GPIO_Speed = gpio->speed;
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
    #endif
    #if defined(STM32F10X_HD)
    switch(port) {
        case (uint32_t)GPIOA: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); break;
        case (uint32_t)GPIOB: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); break;
        case (uint32_t)GPIOC: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); break;
        case (uint32_t)GPIOD: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); break;
        case (uint32_t)GPIOE: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); break;
        case (uint32_t)GPIOF: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); break;
        case (uint32_t)GPIOG: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); break;
        default: return -1;
    }
    switch (speed) {
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_Speed_2MHz; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_Speed_10MHz; break;
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_Speed_50MHz;  break;
        default: gpio->speed = GPIO_Speed_2MHz; break;
    }
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Speed = gpio->speed;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio->mode = mode;
    gpio->otype = otype;
    gpio->pull = pull;
    if (mode == GPIO_LL_MODE_INPUT) {
        switch (pull) {
            case GPIO_LL_PULL_NO: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
            case GPIO_LL_PULL_UP: gpio_cfg.GPIO_Mode = GPIO_Mode_IPU; break;
            case GPIO_LL_PULL_DOWN: gpio_cfg.GPIO_Mode = GPIO_Mode_IPD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
        }
    } else if (mode == GPIO_LL_MODE_OUTPUT){
        switch (otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    } else if (mode == GPIO_LL_MODE_ANALOG) {
        gpio_cfg.GPIO_Mode = GPIO_Mode_AIN;
    } else if (mode == GPIO_LL_MODE_AF) {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        switch (otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    }
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
    // clang-format on
    #endif
#elif defined(PY32F071xB)
    // clang-format off
    gpio->port = port;
    gpio->pin = pinnum;
    switch (port) {
    case (uint32_t)GPIOA: __HAL_RCC_GPIOA_CLK_ENABLE(); break;
    case (uint32_t)GPIOB: __HAL_RCC_GPIOB_CLK_ENABLE(); break;
    case (uint32_t)GPIOC: __HAL_RCC_GPIOC_CLK_ENABLE(); break;
    case (uint32_t)GPIOF: __HAL_RCC_GPIOF_CLK_ENABLE(); break;
    default: return -1;
    }
    GPIO_InitTypeDef gpio_cfg;
    switch (mode) {
    case GPIO_LL_MODE_INPUT: gpio_cfg.Mode = GPIO_MODE_INPUT; break;
    case GPIO_LL_MODE_OUTPUT: gpio_cfg.Mode = otype == GPIO_LL_OTYPE_OD ? GPIO_MODE_OUTPUT_OD : GPIO_MODE_OUTPUT_PP; break;
    case GPIO_LL_MODE_ANALOG: gpio_cfg.Mode = GPIO_MODE_ANALOG; break;
    case GPIO_LL_MODE_AF: gpio_cfg.Mode = otype == GPIO_LL_OTYPE_OD ? GPIO_MODE_AF_OD : GPIO_MODE_AF_PP; break;
    default: return -1;
    }
    switch (pull) {
    case GPIO_LL_PULL_NO: gpio_cfg.Pull = GPIO_NOPULL; break;
    case GPIO_LL_PULL_UP: gpio_cfg.Pull = GPIO_PULLUP; break;
    case GPIO_LL_PULL_DOWN: gpio_cfg.Pull = GPIO_PULLDOWN; break;
    default: return -1;
    }
    switch (speed) {
    case GPIO_LL_SPEED_LOW: gpio_cfg.Speed = GPIO_SPEED_FREQ_LOW; break;
    case GPIO_LL_SPEED_MEDIUM: gpio_cfg.Speed = GPIO_SPEED_FREQ_MEDIUM; break;
    case GPIO_LL_SPEED_HIGH: gpio_cfg.Speed = GPIO_SPEED_FREQ_HIGH; break;
    case GPIO_LL_SPEED_VERY_HIGH: gpio_cfg.Speed = GPIO_SPEED_FREQ_VERY_HIGH; break;
    default: return -1;
    }
    gpio_cfg.Pin = pinnum;
    gpio->mode = gpio_cfg.Mode;
    gpio->pull = gpio_cfg.Pull;
    gpio->speed = gpio_cfg.Speed;
    gpio->af_num = gpio_cfg.Alternate = af_num;
    HAL_GPIO_Init((void *)port, &gpio_cfg);
    return 0;
    // clang-format on
#endif
    return -1;
}
/**
 * @brief gpio反初始化
 * @param  gpio             
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_deinit(gpio_ll_t *gpio) {
    // todo
    return -1;
}

/**
 * @brief 设置输出类型
 * @param  gpio
 * @param  otype
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_set_outtype(gpio_ll_t *gpio, gpio_ll_outtype_t otype) {
    // clang-format off
#if defined(GD32F407)
    switch (otype) {
    case GPIO_LL_OTYPE_PP: gpio->otype = GPIO_OTYPE_PP; break;
    case GPIO_LL_OTYPE_OD: gpio->otype = GPIO_OTYPE_OD; break;
    default: gpio->otype = GPIO_OTYPE_PP; break;
    }
    gpio_output_options_set(gpio->port, gpio->otype, gpio->speed, gpio->pin);
    return 0;
#elif defined(GD32F10X_HD)
    gpio->otype = otype;
    if (gpio->mode == GPIO_LL_MODE_INPUT) {
        switch (gpio->pull) {
            case GPIO_LL_PULL_NO: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_UP: gpio_init(gpio->port, GPIO_MODE_IPU, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_DOWN: gpio_init(gpio->port, GPIO_MODE_IPD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_OUTPUT){
        switch (otype) {
            case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_OUT_PP, gpio->speed, gpio->pin); break;
            case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_ANALOG) {
        gpio_init(gpio->port, GPIO_MODE_AIN, gpio->speed, gpio->pin);
    } else if (gpio->mode == GPIO_LL_MODE_AF) {
        rcu_periph_clock_enable(RCU_AF);
        switch (otype) {
        case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_AF_OD, gpio->speed, gpio->pin); break;
        case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_AF_PP, gpio->speed, gpio->pin); break;
        default: return -1;
        }
    }
    return 0;
#elif defined(STM32F40_41xxx)
    switch (otype) {
        case GPIO_LL_OTYPE_PP: gpio->otype = GPIO_OType_PP; break;
        case GPIO_LL_OTYPE_OD: gpio->otype = GPIO_OType_OD; break;
        default: gpio->otype = GPIO_OType_PP; break;
    }
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio_cfg.GPIO_Mode = gpio->mode;
    gpio_cfg.GPIO_OType = gpio->otype;
    gpio_cfg.GPIO_PuPd = gpio->pull;
    gpio_cfg.GPIO_Speed = gpio->speed;
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(STM32F10X_HD)
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Speed = gpio->speed;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio->otype = otype;
    if (gpio->mode == GPIO_LL_MODE_INPUT) {
        switch (gpio->pull) {
            case GPIO_LL_PULL_NO: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
            case GPIO_LL_PULL_UP: gpio_cfg.GPIO_Mode = GPIO_Mode_IPU; break;
            case GPIO_LL_PULL_DOWN: gpio_cfg.GPIO_Mode = GPIO_Mode_IPD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_OUTPUT){
        switch (otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_ANALOG) {
        gpio_cfg.GPIO_Mode = GPIO_Mode_AIN;
    } else if (gpio->mode == GPIO_LL_MODE_AF) {
        switch (otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    }
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(PY32F071xB)
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.Pin = gpio->pin;
    gpio_cfg.Pull = gpio->pull;
    gpio_cfg.Speed = gpio->speed;
    gpio_cfg.Alternate = gpio->af_num;
    if ((gpio->mode == GPIO_MODE_OUTPUT_OD) || (gpio->mode == GPIO_MODE_OUTPUT_PP)) {
        gpio_cfg.Mode = gpio->otype == GPIO_LL_OTYPE_OD ? GPIO_MODE_OUTPUT_OD : GPIO_MODE_OUTPUT_PP;
    } else if((gpio->mode == GPIO_MODE_AF_OD) || (gpio->mode == GPIO_MODE_AF_PP)) {
        gpio_cfg.Mode = gpio->otype == GPIO_LL_OTYPE_OD ? GPIO_MODE_AF_OD : GPIO_MODE_AF_PP;
    }
    gpio->mode = gpio_cfg.Mode;
    HAL_GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#endif
    return -1;
    // clang-format on
}
/**
 * @brief 设置上下拉电阻
 * @param  gpio
 * @param  pull
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_set_pull(gpio_ll_t *gpio, gpio_ll_pull_t pull) {
    // clang-format off
#if defined(GD32F407)
    switch (pull) {
    case GPIO_LL_PULL_NO: gpio->pull = GPIO_PUPD_NONE; break;
    case GPIO_LL_PULL_UP: gpio->pull = GPIO_PUPD_PULLUP; break;
    case GPIO_LL_PULL_DOWN: gpio->pull = GPIO_PUPD_PULLDOWN; break;
    default: gpio->pull = GPIO_PUPD_NONE; break;
    }
    gpio_output_options_set(gpio->port, gpio->otype, gpio->speed, gpio->pin);
    return 0;
#elif defined(GD32F10X_HD)
    gpio->pull = pull;
    if (gpio->mode == GPIO_LL_MODE_INPUT) {
        switch (pull) {
            case GPIO_LL_PULL_NO: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_UP: gpio_init(gpio->port, GPIO_MODE_IPU, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_DOWN: gpio_init(gpio->port, GPIO_MODE_IPD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_OUTPUT){
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_OUT_PP, gpio->speed, gpio->pin); break;
            case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_ANALOG) {
        gpio_init(gpio->port, GPIO_MODE_AIN, gpio->speed, gpio->pin);
    } else if (gpio->mode == GPIO_LL_MODE_AF) {
        rcu_periph_clock_enable(RCU_AF);
        switch (gpio->otype) {
        case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_AF_OD, gpio->speed, gpio->pin); break;
        case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_AF_PP, gpio->speed, gpio->pin); break;
        default: return -1;
        }
    }
    return 0;
#elif defined(STM32F40_41xxx)
    switch (pull) {
        case GPIO_LL_PULL_NO: gpio->pull = GPIO_PuPd_NOPULL; break;
        case GPIO_LL_PULL_UP: gpio->pull = GPIO_PuPd_UP; break;
        case GPIO_LL_PULL_DOWN: gpio->pull = GPIO_PuPd_DOWN; break;
        default: gpio->pull = GPIO_PuPd_NOPULL; break;
    }
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio_cfg.GPIO_Mode = gpio->mode;
    gpio_cfg.GPIO_OType = gpio->otype;
    gpio_cfg.GPIO_PuPd = gpio->pull;
    gpio_cfg.GPIO_Speed = gpio->speed;
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(STM32F10X_HD)
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Speed = gpio->speed;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio->pull = pull;
    if (gpio->mode == GPIO_LL_MODE_INPUT) {
        switch (pull) {
            case GPIO_LL_PULL_NO: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
            case GPIO_LL_PULL_UP: gpio_cfg.GPIO_Mode = GPIO_Mode_IPU; break;
            case GPIO_LL_PULL_DOWN: gpio_cfg.GPIO_Mode = GPIO_Mode_IPD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_OUTPUT){
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_ANALOG) {
        gpio_cfg.GPIO_Mode = GPIO_Mode_AIN;
    } else if (gpio->mode == GPIO_LL_MODE_AF) {
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    }
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(PY32F071xB)
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.Pin = gpio->pin;
    gpio_cfg.Mode = gpio->mode;
    gpio_cfg.Speed = gpio->speed;
    gpio_cfg.Alternate = gpio->af_num;
    switch (pull) {
    case GPIO_LL_PULL_NO: gpio_cfg.Pull = GPIO_NOPULL; break;
    case GPIO_LL_PULL_UP: gpio_cfg.Pull = GPIO_PULLUP; break;
    case GPIO_LL_PULL_DOWN: gpio_cfg.Pull = GPIO_PULLDOWN; break;
    default: return -1;
    }
    gpio->pull = gpio_cfg.Pull;
    HAL_GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#endif
    return -1;
    // clang-format on
}
/**
 * @brief 设置gpio速度
 * @param  gpio
 * @param  speed
 * @return int 0成 -1失败
 * @note null
 */
int gpio_ll_set_speed(gpio_ll_t *gpio, gpio_ll_speed_t speed) {
    // clang-format off
#if defined(GD32F407)
    switch (speed) {
    case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_OSPEED_2MHZ; break;
    case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_OSPEED_25MHZ; break;
    case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_OSPEED_50MHZ; break;
    case GPIO_LL_SPEED_VERY_HIGH: gpio->speed = GPIO_OSPEED_MAX; break;
    default: gpio->speed = GPIO_OSPEED_2MHZ; break;
    }
    
    gpio_output_options_set(gpio->port, gpio->otype, gpio->speed, gpio->pin);
    return 0;
#elif defined(GD32F10X_HD)
    gpio->speed = speed;
    switch (speed) {
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_OSPEED_2MHZ; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_OSPEED_10MHZ; break;
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_OSPEED_50MHZ;  break;
        default: gpio->speed = GPIO_OSPEED_2MHZ; break;
    }
    if (gpio->mode == GPIO_LL_MODE_INPUT) {
        switch (gpio->pull) {
            case GPIO_LL_PULL_NO: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_UP: gpio_init(gpio->port, GPIO_MODE_IPU, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_DOWN: gpio_init(gpio->port, GPIO_MODE_IPD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_OUTPUT){
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_OUT_PP, gpio->speed, gpio->pin); break;
            case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_ANALOG) {
        gpio_init(gpio->port, GPIO_MODE_AIN, gpio->speed, gpio->pin);
    } else if (gpio->mode == GPIO_LL_MODE_AF) {
        rcu_periph_clock_enable(RCU_AF);
        switch (gpio->otype) {
        case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_AF_OD, gpio->speed, gpio->pin); break;
        case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_AF_PP, gpio->speed, gpio->pin); break;
        default: return -1;
        }
    }
    return 0;
#elif defined(STM32F40_41xxx)
    switch (speed) {
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_Speed_2MHz; break;
        case GPIO_LL_SPEED_VERY_HIGH: gpio->speed = GPIO_Speed_100MHz; break;
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_Speed_50MHz; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_Speed_25MHz; break;
        default: gpio->speed = GPIO_Speed_2MHz; break;
    }
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio_cfg.GPIO_Mode = gpio->mode;
    gpio_cfg.GPIO_OType = gpio->otype;
    gpio_cfg.GPIO_PuPd = gpio->pull;
    gpio_cfg.GPIO_Speed = gpio->speed;
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(STM32F10X_HD)
    GPIO_InitTypeDef gpio_cfg;
    switch (speed) {
    #if defined(STM32F40_41xxx)
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_OSPEED_2MHZ; break;
        case GPIO_LL_SPEED_VERY_HIGH: gpio->speed = GPIO_OSPEED_MAX; break;
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_OSPEED_50MHZ; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_OSPEED_25MHZ; break;
    #elif defined(STM32F10X_HD)
        case GPIO_LL_SPEED_LOW: gpio->speed = GPIO_Speed_2MHz; break;
        case GPIO_LL_SPEED_MEDIUM: gpio->speed = GPIO_Speed_10MHz; break;
        case GPIO_LL_SPEED_HIGH: gpio->speed = GPIO_Speed_50MHz;  break;
    #endif
        default: gpio->speed = GPIO_Speed_2MHz; break;
    }
    gpio_cfg.GPIO_Speed = gpio->speed;
    gpio_cfg.GPIO_Pin = gpio->pin;
    if (gpio->mode == GPIO_LL_MODE_INPUT) {
        switch (gpio->pull) {
            case GPIO_LL_PULL_NO: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
            case GPIO_LL_PULL_UP: gpio_cfg.GPIO_Mode = GPIO_Mode_IPU; break;
            case GPIO_LL_PULL_DOWN: gpio_cfg.GPIO_Mode = GPIO_Mode_IPD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_OUTPUT){
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    } else if (gpio->mode == GPIO_LL_MODE_ANALOG) {
        gpio_cfg.GPIO_Mode = GPIO_Mode_AIN;
    } else if (gpio->mode == GPIO_LL_MODE_AF) {
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    }
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(PY32F071xB)
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.Pin = gpio->pin;
    gpio_cfg.Mode = gpio->mode;
    gpio_cfg.Pull = gpio->pull;
    gpio_cfg.Alternate = gpio->af_num;
    switch (speed) {
    case GPIO_LL_SPEED_LOW: gpio_cfg.Speed = GPIO_SPEED_FREQ_LOW; break;
    case GPIO_LL_SPEED_MEDIUM: gpio_cfg.Speed = GPIO_SPEED_FREQ_MEDIUM; break;
    case GPIO_LL_SPEED_HIGH: gpio_cfg.Speed = GPIO_SPEED_FREQ_HIGH; break;
    case GPIO_LL_SPEED_VERY_HIGH: gpio_cfg.Speed = GPIO_SPEED_FREQ_VERY_HIGH; break;
    default: return -1;
    }
    gpio->speed = gpio_cfg.Speed;
    HAL_GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#endif
    return -1;
    // clang-format on
}


/**********************************Private Functions*******************************/


/* [] END OF FILE */
